package org.speedy.util;

import static org.junit.Assert.*;

import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.speedy.analysis.AnalysisResult;

@SuppressWarnings("unchecked")
public class UnitTestBase {

	protected Assertor<AnalysisResult> hasOnly(final Class ... wantedTests) {
		return new Assertor<AnalysisResult>() {
			public void assertValue(AnalysisResult value) {
				Set<String> testsToRun = value.getTestsToRun();
				assertEquals(wantedTests.length, testsToRun.size());
				
				for (Class wantedTest : wantedTests) {
					assertThat(testsToRun, hasStringThatContains(wantedTest.getSimpleName()));
				}
			}
		};
	}

	protected Assertor<Collection<String>> hasStringThatContains(final String substring) {
		return new Assertor<Collection<String>>() {
			public void assertValue(Collection<String> value) {
				boolean found = false;
				for (String s : value) {
					found = s.contains(substring);
					if (found) {
						break;
					}
				}
				assertTrue(found);
			}
		};
	}

	//TODO remove?
	protected Assertor<AnalysisResult> doesNotHave(final Class test) {
		return new Assertor<AnalysisResult>() {
			public void assertValue(AnalysisResult value) {
				Set<String> testsToRun = value.getTestsToRun();
				
				for (String testToRun : testsToRun) {
					assertFalse(testToRun.contains(test.getSimpleName()));
				}
			}
		};
	}
	
	//I'm really tired of matchers, enter the assertor!
	protected <T> void assertThat(T o, Assertor<T> a) {
		a.assertValue(o);
	}

	protected String nameFor(Class clazz) {
		return clazz.getName().replaceAll("\\.", "/");
	}

	protected Assertor<AnalysisResult> findsDependencies(final List<String> dependencies) {
		return new Assertor<AnalysisResult>() {
			public void assertValue(AnalysisResult value) {
				for (String d : dependencies) {
					if(!value.getAnalyzedClasses().contains(d)) {
						fail("should contain: " + d);
					}
				}
			}
		};
	}
}